home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / GCC 1.37.1r14 / usr / lib / string / strftime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-20  |  7.0 KB  |  303 lines  |  [TEXT/CPED]

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)strftime.c    5.11 (Berkeley) 2/24/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40. #include <tzfile.h>
  41. #include <string.h>
  42.  
  43. static char *afmt[] = {
  44.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
  45. };
  46. static char *Afmt[] = {
  47.     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
  48.     "Saturday",
  49. };
  50. static char *bfmt[] = {
  51.     "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
  52.     "Oct", "Nov", "Dec",
  53. };
  54. static char *Bfmt[] = {
  55.     "January", "February", "March", "April", "May", "June", "July",
  56.     "August", "September", "October", "November", "December",
  57. };
  58.  
  59. static size_t gsize;
  60. static char *pt;
  61. #ifdef __STDC__
  62. static _add(register char *str);
  63. static _conv(int n, int digits, char pad);
  64. static _secs(const struct tm *t);
  65. static size_t _fmt(register const char *format,const struct tm *t);
  66. #else
  67. static int _add(), _conv(), _secs();
  68. static size_t _fmt();
  69. #endif
  70.  
  71. size_t
  72. strftime(s, maxsize, format, t)
  73.     char *s;
  74.     size_t maxsize;
  75.     const char *format;
  76.     const struct tm *t;
  77. {
  78.  
  79.     pt = s;
  80.     if ((gsize = maxsize) < 1)
  81.         return(0);
  82.     if (_fmt(format, t)) {
  83.         *pt = '\0';
  84.         return(maxsize - gsize);
  85.     }
  86.     return(0);
  87. }
  88.  
  89. static size_t
  90. _fmt(format, t)
  91.     register const char *format;
  92.     const struct tm *t;
  93. {
  94.     for (; *format; ++format) {
  95.         if (*format == '%')
  96.             switch(*++format) {
  97.             case '\0':
  98.                 --format;
  99.                 break;
  100.             case 'A':
  101.                 if (t->tm_wday < 0 || t->tm_wday > 6)
  102.                     return(0);
  103.                 if (!_add(Afmt[t->tm_wday]))
  104.                     return(0);
  105.                 continue;
  106.             case 'a':
  107.                 if (t->tm_wday < 0 || t->tm_wday > 6)
  108.                     return(0);
  109.                 if (!_add(afmt[t->tm_wday]))
  110.                     return(0);
  111.                 continue;
  112.             case 'B':
  113.                 if (t->tm_mon < 0 || t->tm_mon > 11)
  114.                     return(0);
  115.                 if (!_add(Bfmt[t->tm_mon]))
  116.                     return(0);
  117.                 continue;
  118.             case 'b':
  119.             case 'h':
  120.                 if (t->tm_mon < 0 || t->tm_mon > 11)
  121.                     return(0);
  122.                 if (!_add(bfmt[t->tm_mon]))
  123.                     return(0);
  124.                 continue;
  125.             case 'C':
  126.                 if (!_fmt("%a %b %e %H:%M:%S %Y", t))
  127.                     return(0);
  128.                 continue;
  129.             case 'c':
  130.                 if (!_fmt("%m/%d/%y %H:%M:%S", t))
  131.                     return(0);
  132.                 continue;
  133.             case 'D':
  134.                 if (!_fmt("%m/%d/%y", t))
  135.                     return(0);
  136.                 continue;
  137.             case 'd':
  138.                 if (!_conv(t->tm_mday, 2, '0'))
  139.                     return(0);
  140.                 continue;
  141.             case 'e':
  142.                 if (!_conv(t->tm_mday, 2, ' '))
  143.                     return(0);
  144.                 continue;
  145.             case 'H':
  146.                 if (!_conv(t->tm_hour, 2, '0'))
  147.                     return(0);
  148.                 continue;
  149.             case 'I':
  150.                 if (!_conv(t->tm_hour % 12 ?
  151.                     t->tm_hour % 12 : 12, 2, '0'))
  152.                     return(0);
  153.                 continue;
  154.             case 'j':
  155.                 if (!_conv(t->tm_yday + 1, 3, '0'))
  156.                     return(0);
  157.                 continue;
  158.             case 'k':
  159.                 if (!_conv(t->tm_hour, 2, ' '))
  160.                     return(0);
  161.                 continue;
  162.             case 'l':
  163.                 if (!_conv(t->tm_hour % 12 ?
  164.                     t->tm_hour % 12 : 12, 2, ' '))
  165.                     return(0);
  166.                 continue;
  167.             case 'M':
  168.                 if (!_conv(t->tm_min, 2, '0'))
  169.                     return(0);
  170.                 continue;
  171.             case 'm':
  172.                 if (!_conv(t->tm_mon + 1, 2, '0'))
  173.                     return(0);
  174.                 continue;
  175.             case 'n':
  176.                 if (!_add("\n"))
  177.                     return(0);
  178.                 continue;
  179.             case 'p':
  180.                 if (!_add(t->tm_hour >= 12 ? "PM" : "AM"))
  181.                     return(0);
  182.                 continue;
  183.             case 'R':
  184.                 if (!_fmt("%H:%M", t))
  185.                     return(0);
  186.                 continue;
  187.             case 'r':
  188.                 if (!_fmt("%I:%M:%S %p", t))
  189.                     return(0);
  190.                 continue;
  191.             case 'S':
  192.                 if (!_conv(t->tm_sec, 2, '0'))
  193.                     return(0);
  194.                 continue;
  195.             case 's':
  196.                 if (!_secs(t))
  197.                     return(0);
  198.                 continue;
  199.             case 'T':
  200.             case 'X':
  201.                 if (!_fmt("%H:%M:%S", t))
  202.                     return(0);
  203.                 continue;
  204.             case 't':
  205.                 if (!_add("\t"))
  206.                     return(0);
  207.                 continue;
  208.             case 'U':
  209.                 if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7,
  210.                     2, '0'))
  211.                     return(0);
  212.                 continue;
  213.             case 'W':
  214.                 if (!_conv((t->tm_yday + 7 -
  215.                     (t->tm_wday ? (t->tm_wday - 1) : 6))
  216.                     / 7, 2, '0'))
  217.                     return(0);
  218.                 continue;
  219.             case 'w':
  220.                 if (!_conv(t->tm_wday, 1, '0'))
  221.                     return(0);
  222.                 continue;
  223.             case 'x':
  224.                 if (!_fmt("%m/%d/%y", t))
  225.                     return(0);
  226.                 continue;
  227.             case 'y':
  228.                 if (!_conv((t->tm_year + TM_YEAR_BASE)
  229.                     % 100, 2, '0'))
  230.                     return(0);
  231.                 continue;
  232.             case 'Y':
  233.                 if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0'))
  234.                     return(0);
  235.                 continue;
  236.             case 'Z':
  237.                 if (!t->tm_zone || !_add(t->tm_zone))
  238.                     return(0);
  239.                 continue;
  240.             case '%':
  241.             /*
  242.              * X311J/88-090 (4.12.3.5): if conversion char is
  243.              * undefined, behavior is undefined.  Print out the
  244.              * character itself as printf(3) does.
  245.              */
  246.             default:
  247.                 break;
  248.         }
  249.         if (!gsize--)
  250.             return(0);
  251.         *pt++ = *format;
  252.     }
  253.     return(gsize);
  254. }
  255.  
  256. static
  257. _secs(t)
  258.     const struct tm *t;
  259. {
  260.     static char buf[15];
  261.     register time_t s;
  262.     register char *p;
  263.     struct tm tmp;
  264.  
  265.     /* Make a copy, mktime(3) modifies the tm struct. */
  266.     tmp = *t;
  267.     s = mktime(&tmp);
  268.     for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
  269.         *p-- = s % 10 + '0';
  270.     return(_add(++p));
  271. }
  272.  
  273. #ifdef __STDC__
  274. static _conv(int n, int digits, char pad)
  275. #else
  276. static
  277. _conv(n, digits, pad)
  278.     int n, digits;
  279.     char pad;
  280. #endif
  281. {
  282.     static char buf[10];
  283.     register char *p;
  284.  
  285.     for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
  286.         *p-- = n % 10 + '0';
  287.     while (p > buf && digits-- > 0)
  288.         *p-- = pad;
  289.     return(_add(++p));
  290. }
  291.  
  292. static
  293. _add(str)
  294.     register char *str;
  295. {
  296.     for (;; ++pt, --gsize) {
  297.         if (!gsize)
  298.             return(0);
  299.         if (!(*pt = *str++))
  300.             return(1);
  301.     }
  302. }
  303.